#region using directives

using System;
using System.ComponentModel;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;
using Client.UIHelper;

#endregion

namespace ClientForms
{
    /// <summary>
    /// Summary description for Form1.
    /// </summary>
    /// <exception cref="DataStoreAppConfigException">
    /// If the datastore has not been initialized before the form was created this exception will be thrown.
    /// </exception>
    public class RegisterForm : Form
    {
        #region private form variables

        private string _status;
        private TextBox address;
        private TextBox city;

        /// <summary>
        /// Required designer variable.
        /// </summary>
        private Container components = null;

        private DataStore dataStore;

        private TextBox email;
        private ErrorProvider errNotifier;
        private TextBox firstname;
        private Label label1;
        private Label label2;
        private Label label3;
        private Label label4;
        private Label label5;
        private Label label6;
        private Label label7;
        private Label label8;
        private TextBox lastname;
        private TextBox phone;
        private Serverprocessing sp;
        private TextBox state;
        private Button submit;
        private TextBox zipcode;

        #endregion

        #region constructor

        /// <summary>
        /// The constructor for the Register Form
        /// </summary>
        /// <exception cref="DataStoreAppConfigException">
        /// If the datastore has not been initialized before the form was created this exception will be thrown.
        /// </exception>
        public RegisterForm()
        {
            //
            // Required for Windows Form Designer support
            //
            InitializeComponent();

            errNotifier = new ErrorProvider();

            dataStore = new DataStore(this);


            if (dataStore.PaymentSettings == null)
            {
                string message = "You Cannot use this form until a valid datastore has been received from the web service.";
                MessageBox.Show(message);
                Close();
                throw new DataStoreAppConfigException(message);
            }
        }

        #endregion

        #region dispose

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (components != null)
                {
                    components.Dispose();
                }
                sp.Dispose();
            }
            base.Dispose(disposing);
        }

        #endregion

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.firstname = new System.Windows.Forms.TextBox();
            this.lastname = new System.Windows.Forms.TextBox();
            this.address = new System.Windows.Forms.TextBox();
            this.city = new System.Windows.Forms.TextBox();
            this.state = new System.Windows.Forms.TextBox();
            this.zipcode = new System.Windows.Forms.TextBox();
            this.phone = new System.Windows.Forms.TextBox();
            this.email = new System.Windows.Forms.TextBox();
            this.label1 = new System.Windows.Forms.Label();
            this.label2 = new System.Windows.Forms.Label();
            this.label3 = new System.Windows.Forms.Label();
            this.label4 = new System.Windows.Forms.Label();
            this.label5 = new System.Windows.Forms.Label();
            this.label6 = new System.Windows.Forms.Label();
            this.label7 = new System.Windows.Forms.Label();
            this.label8 = new System.Windows.Forms.Label();
            this.submit = new System.Windows.Forms.Button();
            this.SuspendLayout();
            // 
            // firstname
            // 
            this.firstname.BackColor = System.Drawing.Color.LightGray;
            this.firstname.Location = new System.Drawing.Point(170, 119);
            this.firstname.MaxLength = 32;
            this.firstname.Name = "firstname";
            this.firstname.Size = new System.Drawing.Size(175, 20);
            this.firstname.TabIndex = 0;
            this.firstname.TextChanged += new System.EventHandler(this.firstname_TextChanged);
            // 
            // lastname
            // 
            this.lastname.BackColor = System.Drawing.Color.LightGray;
            this.lastname.Location = new System.Drawing.Point(361, 119);
            this.lastname.MaxLength = 32;
            this.lastname.Name = "lastname";
            this.lastname.Size = new System.Drawing.Size(175, 20);
            this.lastname.TabIndex = 1;
            // 
            // address
            // 
            this.address.BackColor = System.Drawing.Color.LightGray;
            this.address.Location = new System.Drawing.Point(170, 167);
            this.address.MaxLength = 128;
            this.address.Name = "address";
            this.address.Size = new System.Drawing.Size(366, 20);
            this.address.TabIndex = 2;
            // 
            // city
            // 
            this.city.BackColor = System.Drawing.Color.LightGray;
            this.city.Location = new System.Drawing.Point(170, 215);
            this.city.MaxLength = 32;
            this.city.Name = "city";
            this.city.Size = new System.Drawing.Size(175, 20);
            this.city.TabIndex = 3;
            // 
            // state
            // 
            this.state.BackColor = System.Drawing.Color.LightGray;
            this.state.Location = new System.Drawing.Point(362, 215);
            this.state.MaxLength = 32;
            this.state.Name = "state";
            this.state.Size = new System.Drawing.Size(56, 20);
            this.state.TabIndex = 4;
            // 
            // zipcode
            // 
            this.zipcode.BackColor = System.Drawing.Color.LightGray;
            this.zipcode.Location = new System.Drawing.Point(433, 215);
            this.zipcode.MaxLength = 16;
            this.zipcode.Name = "zipcode";
            this.zipcode.Size = new System.Drawing.Size(103, 20);
            this.zipcode.TabIndex = 5;
            // 
            // phone
            // 
            this.phone.BackColor = System.Drawing.Color.LightGray;
            this.phone.Location = new System.Drawing.Point(170, 271);
            this.phone.MaxLength = 32;
            this.phone.Name = "phone";
            this.phone.Size = new System.Drawing.Size(175, 20);
            this.phone.TabIndex = 6;
            // 
            // email
            // 
            this.email.BackColor = System.Drawing.Color.LightGray;
            this.email.Location = new System.Drawing.Point(361, 271);
            this.email.MaxLength = 32;
            this.email.Name = "email";
            this.email.Size = new System.Drawing.Size(175, 20);
            this.email.TabIndex = 8;
            // 
            // label1
            // 
            this.label1.AutoSize = true;
            this.label1.BackColor = System.Drawing.Color.Transparent;
            this.label1.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte) (0)));
            this.label1.Location = new System.Drawing.Point(170, 100);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(62, 13);
            this.label1.TabIndex = 10;
            this.label1.Text = "First Name:";
            // 
            // label2
            // 
            this.label2.AutoSize = true;
            this.label2.BackColor = System.Drawing.Color.Transparent;
            this.label2.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte) (0)));
            this.label2.Location = new System.Drawing.Point(361, 100);
            this.label2.Name = "label2";
            this.label2.Size = new System.Drawing.Size(61, 13);
            this.label2.TabIndex = 11;
            this.label2.Text = "Last Name:";
            // 
            // label3
            // 
            this.label3.AutoSize = true;
            this.label3.BackColor = System.Drawing.Color.Transparent;
            this.label3.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte) (0)));
            this.label3.Location = new System.Drawing.Point(170, 149);
            this.label3.Name = "label3";
            this.label3.Size = new System.Drawing.Size(50, 13);
            this.label3.TabIndex = 12;
            this.label3.Text = "Address:";
            // 
            // label4
            // 
            this.label4.AutoSize = true;
            this.label4.BackColor = System.Drawing.Color.Transparent;
            this.label4.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte) (0)));
            this.label4.Location = new System.Drawing.Point(168, 197);
            this.label4.Name = "label4";
            this.label4.Size = new System.Drawing.Size(30, 13);
            this.label4.TabIndex = 13;
            this.label4.Text = "City:";
            // 
            // label5
            // 
            this.label5.AutoSize = true;
            this.label5.BackColor = System.Drawing.Color.Transparent;
            this.label5.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte) (0)));
            this.label5.Location = new System.Drawing.Point(362, 197);
            this.label5.Name = "label5";
            this.label5.Size = new System.Drawing.Size(37, 13);
            this.label5.TabIndex = 14;
            this.label5.Text = "State:";
            // 
            // label6
            // 
            this.label6.AutoSize = true;
            this.label6.BackColor = System.Drawing.Color.Transparent;
            this.label6.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte) (0)));
            this.label6.Location = new System.Drawing.Point(432, 197);
            this.label6.Name = "label6";
            this.label6.Size = new System.Drawing.Size(53, 13);
            this.label6.TabIndex = 15;
            this.label6.Text = "Zip Code:";
            // 
            // label7
            // 
            this.label7.AutoSize = true;
            this.label7.BackColor = System.Drawing.Color.Transparent;
            this.label7.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte) (0)));
            this.label7.Location = new System.Drawing.Point(170, 250);
            this.label7.Name = "label7";
            this.label7.Size = new System.Drawing.Size(41, 13);
            this.label7.TabIndex = 16;
            this.label7.Text = "Phone:";
            // 
            // label8
            // 
            this.label8.AutoSize = true;
            this.label8.BackColor = System.Drawing.Color.Transparent;
            this.label8.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte) (0)));
            this.label8.Location = new System.Drawing.Point(360, 251);
            this.label8.Name = "label8";
            this.label8.Size = new System.Drawing.Size(39, 13);
            this.label8.TabIndex = 17;
            this.label8.Text = "E-mail:";
            // 
            // submit
            // 
            this.submit.AutoSize = true;
            this.submit.FlatStyle = System.Windows.Forms.FlatStyle.System;
            this.submit.Location = new System.Drawing.Point(296, 356);
            this.submit.Name = "submit";
            this.submit.Size = new System.Drawing.Size(114, 23);
            this.submit.TabIndex = 19;
            this.submit.Text = "Submit";
            this.submit.Click += new System.EventHandler(this.submit_Click);
            // 
            // RegisterForm
            // 
            this.AcceptButton = this.submit;
            this.BackColor = System.Drawing.Color.Silver;
            this.BackgroundImage = global::ClientForms.Resource.registration;
            this.ClientSize = new System.Drawing.Size(569, 415);
            this.Controls.Add(this.submit);
            this.Controls.Add(this.label8);
            this.Controls.Add(this.label7);
            this.Controls.Add(this.label6);
            this.Controls.Add(this.label5);
            this.Controls.Add(this.label4);
            this.Controls.Add(this.label3);
            this.Controls.Add(this.label2);
            this.Controls.Add(this.label1);
            this.Controls.Add(this.email);
            this.Controls.Add(this.phone);
            this.Controls.Add(this.zipcode);
            this.Controls.Add(this.state);
            this.Controls.Add(this.city);
            this.Controls.Add(this.address);
            this.Controls.Add(this.lastname);
            this.Controls.Add(this.firstname);
            this.Name = "RegisterForm";
            this.ShowInTaskbar = false;
            this.Text = "Register";
            this.Closing += new System.ComponentModel.CancelEventHandler(this.RegisterForm_Closing);
            this.Load += new System.EventHandler(this.RegisterForm_Load);
            this.ResumeLayout(false);
            this.PerformLayout();
        }

        #endregion

        #region form event handling

        /// <summary>
        /// this is a required method to use the server processing class.  On successful
        /// submission this event is fired by server processing after the web service call 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void RegisterForm_ProccessingComplete(object sender, ProcessingCompletedEvent e)
        {
            // Map the delegate to the instance method:
            var d = new MarshallThisFuncString(SetRegistrationProcessingCompleted);

            e.FormReference.Invoke(d, new object[] {e.Message});
        }

        private void SetRegistrationProcessingCompleted(string message)
        {
            foreach (Control c in Controls)
            {
                if (c.Name == "statusText")
                {
                    Controls.Remove(c);
                    break;
                }
            }
            var statusText = new TextBox();
            statusText.Multiline = true;
            statusText.BorderStyle = BorderStyle.None;
            statusText.ReadOnly = true;
            statusText.TabStop = false;
            statusText.BackColor = Color.White;
            statusText.Font = new Font("Microsoft Sans Serif", 8.75F, FontStyle.Regular, GraphicsUnit.Point, ((byte) (0)));
            statusText.Name = "statusText";
            statusText.Text = message;
            Graphics grfx = CreateGraphics();
            SizeF sizef = grfx.MeasureString(statusText.Text, statusText.Font, 300);
            statusText.Width = 350;
            statusText.Height = Convert.ToInt32(sizef.Height) + 50;
            statusText.Location = new Point(170, (Height - statusText.Height)/2);
            submit.Enabled = false;
            Controls.Add(statusText);

            submit.Enabled = true;
            submit.Text = "Finish";
        }

        /// <summary>
        /// This is a required method to use the server processing class.  On a web service 
        /// failure this failure message is passed back to the client UI with ProcessingFailedEventArgs
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void RegisterForm_ProccessingFailed(object sender, ProcessingFailedEvent e)
        {
            // Map the delegate to the instance method:
            var d = new MarshallThisFuncFailureInfo(SetRegistrationProcessingFailed);
            e.FormReference.Invoke(d, new object[] {e.FailureInformation});
        }

        /// <summary>
        /// Set the form to a failure state and display the failure message.
        /// </summary>
        /// <param name="message">The failure message to display to the user.</param>
        private void SetRegistrationProcessingFailed(FailureInfo failureInfo)
        {
            _status = "Error";

            foreach (Control c in Controls)
            {
                if (c.Name == "statusText")
                {
                    Controls.Remove(c);
                    break;
                }
            }
            var statusText = new TextBox();
            statusText.Multiline = true;
            statusText.BorderStyle = BorderStyle.None;
            statusText.ReadOnly = true;
            statusText.TabStop = false;
            statusText.BackColor = Color.White;
            statusText.Font = new Font("Microsoft Sans Serif", 8.75F, FontStyle.Regular, GraphicsUnit.Point, ((byte) (0)));
            statusText.Name = "statusText";
            statusText.Text = failureInfo.Message;
            Graphics grfx = CreateGraphics();
            SizeF sizef = grfx.MeasureString(statusText.Text, statusText.Font, 300);
            statusText.Width = 350;
            statusText.Height = Convert.ToInt32(sizef.Height) + 50;
            statusText.Location = new Point(170, (Height - statusText.Height)/2);
            submit.Enabled = false;
            Controls.Add(statusText);


            submit.Enabled = true;
            submit.Text = "Finish";

            if (failureInfo.Alert == FailureInfo.AlertType.Port)
            {
                MessageBox.Show("If the web service cannot be reached please " + "verify that the ASP .NET development port matches the port " + "configured in the application web reference and update as " + "necessary.  The application will need to be restarted after " + "the configuration change.");
            }
        }

        /// <summary>
        /// used to validate the input on the form
        /// </summary>
        /// <param name="control"></param>
        /// <returns></returns>
        private bool ValidateField(Control control)
        {
            FormValidator.ControlValidator validator;

            if (control.Name == "email")
            {
                validator = new FormValidator.ControlValidator(FormValidator.Isemailvalidator);
            }
            else
            {
                validator = new FormValidator.ControlValidator(FormValidator.Hastextvalidator);
            }

            return FormValidator.Fieldisvalid(errNotifier, control, "Required Field", validator);
        }

        /// <summary>
        /// If the button is clicked and the status is submitted or Error then the form is closed.
        /// Otherwise, the UI is initialized to a processing status and the web service is contacted
        /// via the serverProcessing class
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void submit_Click(object sender, EventArgs e)
        {
            if (_status == "submitted" || _status == "Error")
            {
                Close();
            }
            else
            {
                //first validate name and email fields to see if they are populated.  We do this because the IF statement
                //below will only run the first validation if it fails right there, and we want to validate all three fields
                //no matter what
                ValidateField(firstname);
                ValidateField(lastname);
                ValidateField(email);

                if (ValidateField(firstname) && ValidateField(lastname) && ValidateField(email))
                {
                    firstname.Visible = false;
                    lastname.Visible = false;
                    address.Visible = false;
                    city.Visible = false;
                    state.Visible = false;
                    zipcode.Visible = false;
                    phone.Visible = false;
                    email.Visible = false;
                    label1.Visible = false;
                    label2.Visible = false;
                    label3.Visible = false;
                    label4.Visible = false;
                    label5.Visible = false;
                    label6.Visible = false;
                    label7.Visible = false;
                    label8.Visible = false;

                    _status = "submitted";
                    var statusText = new TextBox();
                    statusText.Multiline = true;
                    statusText.BorderStyle = BorderStyle.None;
                    statusText.ReadOnly = true;
                    statusText.TabStop = false;
                    statusText.BackColor = Color.White;
                    statusText.Font = new Font("Microsoft Sans Serif", 8.75F, FontStyle.Regular, GraphicsUnit.Point, ((byte) (0)));
                    statusText.Name = "statusText";
                    statusText.Text = "Your registration is being processed.  This may take a few moments.";
                    Graphics grfx = CreateGraphics();
                    SizeF sizef = grfx.MeasureString(statusText.Text, statusText.Font, 300);
                    statusText.Width = 350;
                    statusText.Height = Convert.ToInt32(sizef.Height) + 50;
                    statusText.Location = new Point(170, (Height - statusText.Height)/2);
                    submit.Enabled = false;
                    Controls.Add(statusText);

                    var dataStore = new DataStore(this);
                    var registerInfo = new RegisterInfo(dataStore.ProductName, dataStore.GetLicenseLevel.LicenseLevel, email.Text, firstname.Text, lastname.Text, dataStore.Devtoken, address.Text, city.Text, state.Text, zipcode.Text, phone.Text, dataStore.UniqueMachineID, this);

                    //Create the new web service processing class and pass in the information to be transmitted
                    sp = new Serverprocessing(registerInfo);

                    //set up the event handlers for the serverProcessing Class
                    sp.Processingcomplete += new EventHandler<ProcessingCompletedEvent>(RegisterForm_ProccessingComplete);
                    sp.Processingfailed += new EventHandler<ProcessingFailedEvent>(RegisterForm_ProccessingFailed);

                    //start the web service on a seperate thread
                    var handleProcessingThreadStarter = new ThreadStart(sp.HandleRegistration);
                    var handleProcessingThread = new Thread(handleProcessingThreadStarter);
                    handleProcessingThread.Start();
                }
            }
        }

        #endregion

        private void RegisterForm_Load(object sender, EventArgs e)
        {
        }

        private void RegisterForm_Closing(object sender, CancelEventArgs e)
        {
            if (sp != null)
            {
                sp.Cancelprocessing();
            }
        }

        private void firstname_TextChanged(object sender, EventArgs e)
        {
        }
    }
}